<?php

/**
 * This file is part of the Pagizer package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright   Copyright (c) 2010 Advisa (http://www.advisa.fr)
 * @author      Pagizer Core Team <team@pagizer.org>
 * @package     Pagizer
 * @subpackage  backoffice
 */

/**
 * Service to make pagination
 */

class m_backoffice_services_ListService extends f_core_Service
{
	private static $instance;

	/* @var $xmlObject f_xml_Xpath */
	private $xmlObject;
    private $moduleName;
	private $parserFileName = "folderList";

	/**
	 * @return m_backoffice_services_TempDocService
	 */
	private function __construct()
	{
		return $this;
	}

	/**
	 * Get singleton instance
	 *
	 * @return m_backoffice_services_TempDocService
	 */
	public static function getInstance()
	{
		if(self::$instance === null)
		{
			self::$instance = new self();
		}
		return self::$instance;
	}

    /**
     * Get the documents with the parameters
     * @param <type> $parentDoc
     * @param <type> $documentsToGet
     * @param <type> $nbDoc
     * @param <type> $numPage
     * @param <type> $sort
     * @param <type> $search
     * @param <type> $nb
     * @return <type> array or int
     */
    public function getDocuments($parentDoc, $documentsToGet, $nbDoc, $numPage, $sort = array(), $search = array(), $nb = false)
    {
        $lang = $this->getContextLang();

        $request = $this->getDocumentProvider()
                        ->loadDocuments($documentsToGet[0]);

        if(!is_null($parentDoc))
        {
            $request->isChildOf($parentDoc->getUniqueId(), null, true);
            $lang = $parentDoc->getLang();
        }

        if(!empty($sort) || !empty($search))
        {
            if(isset($sort['order']) && !is_null($sort['order']) && $sort['order'] != '' && isset($sort['column']) && !is_null($sort['column']))
            {
                $method = 'add'.ucfirst($sort["order"]).'Order';
                $request->$method($sort["column"]);
            }

            if(!empty($search))
            {
                foreach($search as $key => $value)
                {
                    if(!empty($value))
                    {
                        if(preg_match("#[0-9]+/[0-9]+/[0-9]+#", $value))
                        {
                            $value = f_date_Date::getInstanceFromFormat($value, "d/m/Y")->toString();
                            $value = f_date_DateFormat::format($value, "Y-m-d");
                        }

                        $request->whereLike($key, "%".$value."%");
                    }
                }
            }

            if(!$nb && !is_null($nbDoc) && !is_null($numPage))
            {
                $numPage = $nbDoc*($numPage-1);
                $numPage = ($numPage < 0) ? 0 : $numPage;

                $request->limit($nbDoc, $numPage);
            }
        }

        $result = $request->retrieveDocuments();

        $user = $this->getUserContext()->getUser();

        foreach($result as $key => $value)
        {
            if(!$user->hasDocRight($value, $this->moduleName, 'read'))
            {
                unset($result[$key]);
            }
        }

        if($nb == true)
        {
            return count($result);
        }

        if(!empty($search) && empty($result))
        {
            $this->getContext()->removeContext("searchParams_".$this->moduleName);
            return "search";
        }

        return $result;
    }

    public function getNextDocument($document, $rules = array())
    {
        $parent = f_relation_ManagerNew::getInstance($document)->getParents()->withRelationType($document->getDocumentTypeName())->retrieveDocuments();
        $nextDoc = f_relation_ManagerNew::getInstance($parent[0])->getNextDocument($document, $document->getDocumentTypeName());

        if(is_null($nextDoc))
        {
            return null;
        }

        $user = f_context_User::getInstance()->getUser();
        return ($user->hasDocRight($nextDoc, $nextDoc->getDocumentModuleName(), $rules)) ? $nextDoc : $this->getNextDocument($nextDoc);
    }

    public function getPreviousDocument($document, $rules = array())
    {
        $parent = f_relation_ManagerNew::getInstance($document)->getParents()->withRelationType($document->getDocumentTypeName())->retrieveDocuments();
        $prevDoc = f_relation_ManagerNew::getInstance($parent[0])->getPreviousDocument($document, $document->getDocumentTypeName());

        if(is_null($prevDoc))
        {
            return null;
        }

        $user = f_context_User::getInstance()->getUser();
        return ($user->hasDocRight($prevDoc, $prevDoc->getDocumentModuleName(), $rules)) ? $prevDoc : $this->getPreviousDocument($prevDoc);
    }

    /**
     * Get the documents by the moduleName
     * @param <type> $moduleName
     * @param <type> $parentDoc
     * @param <type> $nbDoc
     * @param <type> $numPage
     * @param <type> $sort
     * @param <type> $search
     * @param <type> $nb
     * @return <type> array or int
     */
	public function getDocumentsByModuleName($parentDoc, $nbDoc, $numPage, $sort = array(), $search = array(), $nb = false)
	{
        $documentsToGet = $this->getAuthorizedDocTypes();
        return $this->getDocuments($parentDoc, $documentsToGet, $nbDoc, $numPage, $sort,  $search, $nb);
	}

	public function getXmlFilePath($moduleName)
	{
        $this->moduleName = $moduleName;
        $xmlFileName = str_replace(".xml", "", $this->parserFileName).".xml";

        $file = f_file_Resolver::getModuleFilePath($moduleName, 'config'.DS.$xmlFileName);

		if(!is_null($file))
		{
			$this->xmlObject = f_xml_Xpath::getInstance($file);
		}
        else
        {
            return null;
        }

		return $this;
	}

	/**
	 * Returns authorized document types to display in list
	 *
	 * @return array|null
	 */
	public function getAuthorizedDocTypes()
	{
		$list = $this->xmlObject->fromXpath("list");
		return explode(",", $list->getAttributeValue('documents'));
	}

    public function getModuleListedDocuments($moduleName)
    {
        $treeDocuments = m_backoffice_services_MenuService::getInstance()->parseModuleTreefile($moduleName)->getAuthorizedDocTypes();

        switch($moduleName)
        {
            case "website":
                $listDocuments = $treeDocuments;
            break;
            case "medias":
                $treeDocuments[] = "modules_medias/media";
                $listDocuments = $treeDocuments;
            break;
            default:
                $listService = m_backoffice_services_ListService::getInstance();
                $listDocuments = $listService->getXmlFilePath($moduleName);
                if(!is_null($listDocuments))
                {
                    $listDocuments = $listDocuments->getAuthorizedDocTypes();
                    $listDocuments = array_merge($listDocuments, $treeDocuments);
                }
                else
                {
                    $listDocuments = $treeDocuments;
                }
            break;
        }

        return $listDocuments;
    }

	public function getXmlConfig($parentDoc)
	{
		$xmlObject = $this->xmlObject;

		$result["firstTabLabel"] = $xmlObject->getAttributeValue("label");
		$result["firstTabLink"] = f_core_Routing::getUrl("genericDocumentTabList", array("docId" => $parentDoc->getUniqueId(), "docLang" => strtolower($parentDoc->getLang()), "configModule" => $this->moduleName, "tabName" => "files"));
		$result["secondTabLink"] = f_core_Routing::getUrl("genericDocumentTabList", array("docId" => $parentDoc->getUniqueId(), "docLang" => strtolower($parentDoc->getLang()), "configModule" => $this->moduleName, "tabName" => "properties"));
		$result["newDocumentRoute"] = f_core_Routing::getUrl($xmlObject->getAttributeValue("newDocumentRoute"), array("docId" => $parentDoc->getUniqueId(), "docLang" => strtolower($parentDoc->getLang())));
        $result["deleteRecursive"] = $xmlObject->getAttributeValue("deleteRecursive", false);

		return $result;
	}

    public function getDefaultNbDoc()
    {
        return $this->xmlObject->fromXpath("list")->getAttributeValue("limit", "10");
    }

    public function isSortable()
    {
        $value = $this->xmlObject->fromXpath("list")->getAttributeValue("sortable", 'true');
        return $value == 'true';
    }

	public function getColumns()
	{
	    $xmlObject = $this->xmlObject;

	    $columns = $xmlObject->getElementsFromXpath("list/col");

	    $result = array();

	    if(count($columns) > 0)
	    {
            /* @var $column f_xml_XmlElement */
            foreach($columns as $i => $column)
            {
                $result[$i]["column"] = $column->getAttributes();

                $searchType = null;
                if(isset($result[$i]["column"]["search"]))
                {
                    $searchType = $this->getSearchType($result[$i]["column"]["search"]);
                }
                $result[$i]["search"] = $searchType;
            }
	    }

	    return $result;
	}

// ***********************************************************************************************

    
    /**
     * Get the parameters for the search bar list
     * @param <type> $moduleName
     * @param <type> $searchValues
     * @return <type> array
     */
    public function getSearchParams($moduleName, $searchValues = null)
    {
        $valuesTab = array();

        $this->moduleName = $moduleName;
        $searchParams = $this->getContext()->getContext("searchParams_".$moduleName);

        if(is_null($searchParams))
        {
            $searchParams = "";
        }

        $searchParams = !is_null($searchValues) ? $searchValues : $searchParams;

        if(!empty($searchParams))
        {
            $valuesTab = array();
            $values = split("[=&]", $searchParams);
            for($i = 0; $i < count($values); $i += 2)
            {
                $valuesTab[$values[$i]] = urldecode($values[$i+1]);
            }
        }

        $this->getContext()->setContext("searchParams_".$moduleName, $searchParams);
        return $valuesTab;
    }

    /**
     * Retrieves information for paging
     * @param <type> $moduleName
     * @param <type> $numPage
     * @param <type> $nbDocTot
     * @param <type> $nbDoc
     * @return <type> array
     */
    public function pagination($moduleName, $nbDocTot, $numPage = null, $nbDoc = null, $defaultNbDoc = 10)
    {
        $this->moduleName = $moduleName;
        $pagination = $this->getContext()->getContext("pagination_".$moduleName);

        if(is_null($pagination))
        {
            $pagination["numPage"] = 1;
            $pagination["nbDoc"] = $defaultNbDoc;
        }

        $pagination["numPage"] = intval($numPage) > 0 ? intval($numPage) : $pagination["numPage"];
		$pagination["nbDoc"] = intval($nbDoc) > 0 ? intval($nbDoc) : $pagination["nbDoc"];
        $pagination["nbDocTot"] = $nbDocTot;

        $nbPageTot = ceil($pagination["nbDocTot"]/$pagination["nbDoc"]);
        if($nbPageTot < $pagination["numPage"])
        {
            $pagination["numPage"] = $nbPageTot;
        }

        $this->getContext()->setContext("pagination_".$moduleName, $pagination);
        return $pagination;
    }

    /**
     * Get the parameters to sort a column
     * @param <type> $moduleName
     * @param <type> $column
     * @param <type> $order
     * @return <type> array
     */
    public function getSortParams($moduleName, $column = null, $order = null)
    {
        $this->moduleName = $moduleName;
        $sortParams = $this->getContext()->getContext("sortParams_".$moduleName);

        if(is_null($sortParams))
        {
            if(is_object($this->xmlObjec))
            {
                $param = $this->xmlObject->fromXpath("list")->getAttributeValue("order", "relation_order/asc");
                list($column, $order) = explode('/', $param);
            }
        }
        $sortParams["column"] = !is_null($column) ? $column : $sortParams["column"];
        $sortParams["order"] = !is_null($order) ? $order : $sortParams["order"];
        $sortParams["class"] = "sort-arrow-".$sortParams["order"];

        $this->getContext()->setContext("sortParams_".$moduleName, $sortParams);
        return $sortParams;
    }

    private function getSearchType($type)
    {
        $tabType = array();
        switch($type)
        {
            default:
            break;

            case "text":
                $tabType["type"] = "text";
            break;

            case "datePicker":
                $tabType["type"] = "text";
                $tabType["class"] = "dateInput";
            break;
        }

        return $tabType;
    }
}